﻿//-----------------------------------------------------------------------
// <copyright file="PivotXmlWriter.cs" company="Forebrain Technology, LLC">
//
// Copyright (c) Forebrain Technology, LLC. All rights reserved.
// 
// This source code is released under the Microsoft Public License (Ms-PL).
//
// </copyright>
//-----------------------------------------------------------------------
namespace PivotCollectionTools.Xml
{
    using System.IO;
    using System.Text;
    using System.Xml;

    /// <summary>
    /// Used to write the Pivot Collection Xml.
    /// </summary>
    internal class PivotXmlWriter : XmlTextWriter
    {
        /// <summary>
        /// If the Tags element started and in the process of writing child Tag elements.
        /// </summary>
        private bool writingTags;

        /// <summary>
        /// Used to determie if the Tags element is empty.
        /// </summary>
        private bool emptyTag;

        /// <summary>
        /// Used to store the Tags element namespace prefix in case the element is not empty.
        /// </summary>
        private string emptyElementPrefix;

        /// <summary>
        /// Used to store the Tags element local name in case the element is not empty.
        /// </summary>
        private string emptyElementLocalName;

        /// <summary>
        /// Used to store the Tags element namespace information in case the element is not empty.
        /// </summary>
        private string emptyElementNameSpace;

        /// <summary>
        /// Initializes a new instance of the <see cref="PivotXmlWriter"/> class.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <param name="encoding">The encoding.</param>
        public PivotXmlWriter(string filename, Encoding encoding)
            : base(filename, encoding)
        {
        }

        /// <summary>
        /// Closes one element and pops the corresponding namespace scope.
        /// </summary>
        public override void WriteEndElement()
        {
            if (this.writingTags && this.emptyTag)
            {
                this.writingTags = false;
                this.emptyTag = false;

                return;
            }

            this.writingTags = false;
            this.emptyTag = false;

            base.WriteEndElement();
        }

        /// <summary>
        /// Writes the specified start tag and associates it with the given namespace and prefix.
        /// If the tag's local name is Tags hold on the output until the child elements can be determined.
        /// If there are not child elements then prevent the Tags element from outputig.
        /// </summary>
        /// <param name="prefix">The namespace prefix of the element.</param>
        /// <param name="localName">The local name of the element.</param>
        /// <param name="ns">The namespace URI to associate with the element. If this namespace is already in scope and has an associated prefix then the writer automatically writes that prefix also.</param>
        /// <exception cref="T:System.InvalidOperationException">
        /// The writer is closed.
        /// </exception>
        public override void WriteStartElement(string prefix, string localName, string ns)
        {
            if (localName == "Tags")
            {
                this.writingTags = true;
                this.emptyTag = true;

                this.emptyElementPrefix = prefix;
                this.emptyElementLocalName = localName;
                this.emptyElementNameSpace = ns;

                return;
            }

            if (localName == "Tag" && this.writingTags)
            {
                this.emptyTag = false;
                base.WriteStartElement(this.emptyElementPrefix, this.emptyElementLocalName, this.emptyElementNameSpace);
            }

            base.WriteStartElement(prefix, localName, ns);
        }

        /// <summary>
        /// Writes the given text content.
        /// </summary>
        /// <param name="text">Text to write.</param>
        /// <exception cref="T:System.ArgumentException">
        /// The text string contains an invalid surrogate pair.
        /// </exception>
        public override void WriteString(string text)
        {
            base.WriteString(text);
        }
    }
}
